package conns

import (
	"fmt"
	"gitee.com/zhongguo168a/go-nodex/nodex/server/message"
	"github.com/pkg/errors"
	"io"
	"net"
	"sync/atomic"
)

func NewTCPSocket(name string, addr string, onReceive func(data interface{})) (obj *TCPSocket) {
	obj = &TCPSocket{
		name:      name,
		addr:      addr,
		onReceive: onReceive,
	}
	return
}

type TCPSocket struct {
	name string
	// 连接地址
	addr string
	//
	seq int16
	//
	conn net.Conn
	// 是否连接
	connected bool
	//
	reqStartTime int64

	lastSeq int32

	onReceive func(data interface{})
}

func (socket *TCPSocket) GetName() string {
	return socket.name
}

func (socket *TCPSocket) GetAddr() string {
	return socket.addr
}

func (socket *TCPSocket) IsConnected() bool {
	return socket.connected
}

func (socket *TCPSocket) Connect() (err error) {
	tcpconn, dialerr := net.Dial("tcp", socket.addr)
	if dialerr != nil {
		return errors.Wrap(dialerr, "dial tcp")
	}
	socket.conn = tcpconn

	socket.connected = true
	go socket.read()
	return
}

func (socket *TCPSocket) read() {
	for {
		tagData := make([]byte, 1)
		_, err := io.ReadFull(socket.conn, tagData)
		if err != nil {
			goto close
		}
		// 将headData字节流 拆包到msg中
		tag := message.PushTag(tagData[0])
		switch tag {
		case message.PushTag_Response:
			msg := &message.ResponseMessage{}
			err = msg.Unpack(socket.conn)
			if err != nil {
				fmt.Printf("[client] unpack ResponseMessage: err = %s\n", err)
				continue
			}
			fmt.Printf("[client] response[%s]: data = %s\n", msg.Route, msg.Data)

			socket.onReceive(msg)

		case message.PushTag_Push:
			msg := &message.PushMessage{}
			err = msg.Unpack(socket.conn, 0)
			if err != nil {
				fmt.Printf("[client] unpack PushMessage: err = %s\n", err)
				continue
			}
			fmt.Printf("[client] server push: data = %s\n", msg.Data)
		case message.PushTag_SyncCreate:
			msg := &message.SyncCreate{}
			err = msg.Unpack(socket.conn, 0)
			if err != nil {
				fmt.Printf("[client] unpack SyncCreate: err = %s\n", err)
				continue
			}
			fmt.Printf("[client] sync create: key=%v, data = %s\n", msg.Key, msg.Data)
		}
	}

close:
	socket.connected = false

}

func (socket *TCPSocket) Send(obj interface{}) {

}

func (socket *TCPSocket) SendByte(msg *message.RequestMessage) (err error) {
	//msgbs, packerr := msg.Pack()
	//if packerr != nil {
	//	err = errors.Wrap(packerr, "pack")
	//	return
	//}
	//_, err = socket.conn.Write(msgbs)
	//if err != nil {
	//	socket.connected = false
	//	return errors.Wrap(err, "write")
	//}
	//
	//socket.reqStartTime = time.Now().UnixNano()
	return
}

func (socket *TCPSocket) getRemoteName(conn net.Conn) (x string) {
	x = conn.RemoteAddr().String()
	return

}

func (socket *TCPSocket) Close() {
	socket.conn.Close()
	return
}

func (socket *TCPSocket) nextSeq() int32 {
	atomic.AddInt32(&socket.lastSeq, 1)
	return socket.lastSeq
}
